package chagine.core.util;

import chagine.core.ErrorCode;
import chagine.core.exception.SeeingRuntimeException;
import chagine.core.restful.util.TResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.ResponseBody;
import org.apache.commons.lang.StringUtils;
import retrofit2.Call;
import retrofit2.Response;

import java.io.IOException;

@Slf4j
public class ApiUtil {

    /**
     * 请求并解析处理API端口，返回Data中数据
     */
    public static <T> T getResponseDataByCall(Call<TResponse<T>> call) {
        return getResponseDataByCall(call, null);
    }

    /**
     * 请求并解析处理API端口，返回Data中数据
     *
     * @param errorMessage 抛出的错误信息
     */
    public static <T> T getResponseDataByCall(Call<TResponse<T>> call, String errorMessage) {
        TResponse<T> tResponse = getResponseByCall(call, errorMessage);
        if (!tResponse.isSuccess()) {
            HttpUrl httpUrl = call.request().url();
            String url = httpUrl.uri().toString();
            log.error("API接口响应失败(DATA),URL[{}] | {}", url, tResponse.getMessage());
        }
        String message = StringUtils.isNotBlank(errorMessage) ? errorMessage + "[" + tResponse.getMessage() + "]" : tResponse.getMessage();
        Assert.error(!tResponse.isSuccess(), ErrorCode.BUSINESS_EXCEPTION, message);
        return tResponse.getData();
    }

    /**
     * 请求并解析处理API端口，返回对象整体
     */
    public static <T> TResponse<T> getResponseByCall(Call<TResponse<T>> call) {
        return getResponseByCall(call, null);
    }

    /**
     * 请求并解析处理API端口，返回对象整体
     */
    public static <T> TResponse<T> getResponseByCall(Call<TResponse<T>> call, String errorMessage) {
        Response<TResponse<T>> response = executeCall(call, errorMessage);
        TResponse<T> tResponse = generateResponseDataThrowError(response, errorMessage);
        if (tResponse == null) {
            HttpUrl httpUrl = call.request().url();
            String url = httpUrl.uri().toString();
            log.error("API接口响应失败(RESPONSE),URL[{}] | {}", url, "请求的响应失败");
        }
        String message = StringUtils.isNotBlank(errorMessage) ? errorMessage + "[请求的响应失败]" : "请求的响应失败";
        Assert.error(tResponse == null, ErrorCode.RUNNING_EXCEPTION, message);
        return tResponse;
    }

    /**
     * 请求远程服务，接收html页面数据
     */
    public static String getResponseHtmlByCall(Call<ResponseBody> call, String errorMessage) {
        Response<ResponseBody> response = executeCall(call, errorMessage);
        Assert.error(!response.isSuccessful(), ErrorCode.BUSINESS_EXCEPTION, StringUtils.isNotBlank(errorMessage) ? errorMessage + "[API远端响应解析异常]" : "API远端响应解析异常");
        // 对发送成功的请求进行处理
        ResponseBody body = response.body();
        Assert.error(body == null, ErrorCode.BUSINESS_EXCEPTION, StringUtils.isNotBlank(errorMessage) ? errorMessage + "[API远端响应数据为空]" : "API远端响应数据为空");
        MediaType mediaType = body.contentType();
        if (mediaType != null && mediaType.toString().contains("text/html")) {
            try {
                return body.string();
            } catch (IOException e) {
                throw new SeeingRuntimeException(ErrorCode.BUSINESS_EXCEPTION, StringUtils.isNotBlank(errorMessage) ? errorMessage + "[API本地处理异常]" : "API本地处理异常");
            }
        }
        throw new SeeingRuntimeException(ErrorCode.BUSINESS_EXCEPTION, StringUtils.isNotBlank(errorMessage) ? errorMessage + "[API远端响应ContentType类型错误]" : "API远端响应ContentType类型错误");
    }

    /**
     * 请求并解析处理API端口，返回对象整体
     */
    public static <T> T getResponseBodyByCall(Call<T> call, String errorMessage) {
        Response<T> response = executeCall(call, errorMessage);
        T data = generateResponseBodyThrowError(response, errorMessage);
        Assert.error(data == null, ErrorCode.RUNNING_EXCEPTION, StringUtils.isNotBlank(errorMessage) ? errorMessage + "[请求的响应失败]" : "请求的响应失败");
        return data;
    }

    /**
     * 请求并解析处理API端口，返回对象整体
     */
    public static <T> T getResponseBodyByCall(Call<T> call) {
        return getResponseBodyByCall(call, null);
    }

    /**
     * 请求远程服务
     */
    public static <T> Response<T> executeCall(Call<T> call) {
        return executeCall(call, null);
    }

    /**
     * 请求远程服务
     */
    public static <T> Response<T> executeCall(Call<T> call, String errorMessage) {
        try {
            return call.execute();
        } catch (IOException e) {
            HttpUrl httpUrl = call.request().url();
            String url = httpUrl.uri().toString();
            log.error("adapter api 远程服务请求异常 [{}] >>>>>", url, e);
            String message = StringUtils.isNotBlank(errorMessage) ? errorMessage + "[远端请求异常]" : "远端请求异常," + e.getMessage();
            throw new SeeingRuntimeException(ErrorCode.RUNNING_EXCEPTION, message);
        }
    }

    /**
     * 返回值处理
     */
    public static <T> TResponse<T> generateResponseDataThrowError(Response<TResponse<T>> response, String errorMessage) {
        if (response.isSuccessful()) {
            okhttp3.Response raw = response.raw();
            ResponseBody body = raw.body();
            if (body != null) {
                return response.body();
            }
        } else {
            TResponse tResponse = errorBody(response, errorMessage);
            if (tResponse != null) {
                return tResponse;
            }
        }
        log.error("API远端请求响应解析异常");
        String message = StringUtils.isNotBlank(errorMessage) ? errorMessage + "[API远端响应解析异常]" : "API远端响应解析异常";
        throw new SeeingRuntimeException(ErrorCode.RUNNING_EXCEPTION, message);
    }

    /**
     * 返回值处理，针对返回值响应结构未知的对象
     */
    public static <T> T generateResponseBodyThrowError(Response<T> response, String errorMessage) {
        if (response.isSuccessful()) {
            okhttp3.Response raw = response.raw();
            ResponseBody body = raw.body();
            if (body != null) {
                return response.body();
            }
        }
        log.error("API远端请求响应解析异常");
        String message = StringUtils.isNotBlank(errorMessage) ? errorMessage + "[API远端响应解析异常]" : "API远端响应解析异常";
        throw new SeeingRuntimeException(ErrorCode.RUNNING_EXCEPTION, message);
    }

    /**
     * 错误的响应体
     */
    private static TResponse errorBody(Response response, String errorMessage) {
        ResponseBody responseBody = response.errorBody();
        if (responseBody != null) {
            MediaType mediaType = responseBody.contentType();
            if (mediaType != null && mediaType.toString().contains("application/json")) {
                try {
                    String responseJson = responseBody.string();
                    ObjectMapper objectMapper = new ObjectMapper();
                    return objectMapper.readValue(responseJson, TResponse.class);
                } catch (IOException e) {
                    log.error("API响应JSON解析异常 >>>>", e);
                    String message = StringUtils.isNotBlank(errorMessage) ? errorMessage + "[API远端响应，JSON转换错误]" : "API远端响应，JSON转换错误：" + e.getMessage();
                    throw new SeeingRuntimeException(ErrorCode.RUNNING_EXCEPTION, message);
                }
            }
        }
        return null;
    }

    /**
     * 解析下载的文件名
     * form-data; name="attachment"; filename="CT831960_0005_00007_CT_256696041.3.12.2.1107.5.1.4.92348.30000021111500121453700042970.dcm"
     */
    public static String getHeaderFileName(okhttp3.Response response) {
        String dispositionHeader = response.header("Content-Disposition");
        if (!StringUtils.isEmpty(dispositionHeader)) {
            dispositionHeader = dispositionHeader.replace("form-data; ", "");
            String[] strings = dispositionHeader.split("; ");
            if (strings.length > 1) {
                dispositionHeader = strings[1].replace("filename=", "");
                dispositionHeader = dispositionHeader.replace("\"", "");
                return dispositionHeader;
            }
            return "";
        }
        return "";
    }

    public static <T> boolean checkServerRunStatus(Call<T> call) {
        try {
            Response<T> response = call.execute();
            okhttp3.Response rawResponse = response.raw();
            return true;
        } catch (Exception e) {
            HttpUrl url = call.request().url();
            log.error("SERVER[URL][{}]服务请求异常", url);
            return false;
        }
    }

}
